using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Linq;
using System.Threading;

namespace DownloadTool
{
    public class TaskPersistence
    {
        private static readonly string TasksFilePath = Path.Combine(
            AppDomain.CurrentDomain.BaseDirectory, "saved_tasks.json");
        
        private static readonly string LogFilePath = Path.Combine(
            AppDomain.CurrentDomain.BaseDirectory, "task_persistence_log.txt");
        
        private static TaskPersistence _instance;
        public static TaskPersistence Instance => _instance ??= new TaskPersistence();
        
        private void LogMessage(string message)
        {
            try
            {
                string logEntry = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}";
                File.AppendAllText(LogFilePath, logEntry + Environment.NewLine);
            }
            catch
            {
                // Ignore logging errors
            }
        }

        // Save both downloading and completed tasks
        public void SaveTasks(ObservableCollection<DownloadTask> downloadingTasks, ObservableCollection<DownloadTask> completedTasks)
        {
            try
            {
                LogMessage($"Saving tasks: {downloadingTasks.Count} downloading, {completedTasks.Count} completed");
                
                // Create serializable data
                var serializableData = new SerializableTaskData();
                
                // Convert downloading tasks
                foreach (var task in downloadingTasks)
                {
                    serializableData.DownloadingTasks.Add(new SerializableTask(task));
                }
                
                // Convert completed tasks
                foreach (var task in completedTasks)
                {
                    serializableData.CompletedTasks.Add(new SerializableTask(task));
                }
                
                var options = new JsonSerializerOptions { 
                    WriteIndented = true,
                    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
                };
                
                string json = JsonSerializer.Serialize(serializableData, options);
                File.WriteAllText(TasksFilePath, json);
                
                LogMessage($"Tasks saved successfully to {TasksFilePath}");
                LogMessage($"JSON size: {json.Length} bytes");
            }
            catch (Exception ex)
            {
                LogMessage($"Error saving tasks: {ex.Message}");
                LogMessage($"Stack trace: {ex.StackTrace}");
            }
        }

        // Load saved tasks
        public TaskData LoadTasks()
        {
            try
            {
                LogMessage($"Attempting to load tasks from {TasksFilePath}");
                
                if (File.Exists(TasksFilePath))
                {
                    string json = File.ReadAllText(TasksFilePath);
                    LogMessage($"Read JSON file, size: {json.Length} bytes");
                    
                    var options = new JsonSerializerOptions { 
                        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
                    };
                    
                    var serializableData = JsonSerializer.Deserialize<SerializableTaskData>(json, options);
                    if (serializableData != null)
                    {
                        LogMessage($"Deserialized task data: {serializableData.DownloadingTasks.Count} downloading, {serializableData.CompletedTasks.Count} completed");
                        
                        // Create new TaskData
                        var taskData = new TaskData();
                        
                        // Convert completed tasks
                        foreach (var serializableTask in serializableData.CompletedTasks)
                        {
                            taskData.CompletedTasks.Add(serializableTask.ToDownloadTask());
                        }
                        
                        // Convert downloading tasks
                        foreach (var serializableTask in serializableData.DownloadingTasks)
                        {
                            taskData.DownloadingTasks.Add(serializableTask.ToDownloadTask());
                        }
                        
                        return taskData;
                    }
                    else
                    {
                        LogMessage("Deserialized task data is null");
                    }
                }
                else
                {
                    LogMessage($"Task file not found: {TasksFilePath}");
                }
            }
            catch (Exception ex)
            {
                LogMessage($"Error loading tasks: {ex.Message}");
                LogMessage($"Stack trace: {ex.StackTrace}");
            }

            // If file doesn't exist or there was an error, return empty data
            LogMessage("Returning empty task data");
            return new TaskData();
        }
    }

    public class TaskData
    {
        public List<DownloadTask> CompletedTasks { get; set; } = new List<DownloadTask>();
        public List<DownloadTask> DownloadingTasks { get; set; } = new List<DownloadTask>();
    }
    
    public class SerializableTaskData
    {
        public List<SerializableTask> CompletedTasks { get; set; } = new List<SerializableTask>();
        public List<SerializableTask> DownloadingTasks { get; set; } = new List<SerializableTask>();
    }
    
    public class SerializableTask
    {
        public string Id { get; set; } = string.Empty;
        public string FileName { get; set; } = string.Empty;
        public string Url { get; set; } = string.Empty;
        public string FilePath { get; set; } = string.Empty;
        public string SavePath { get; set; } = string.Empty;
        public long TotalBytes { get; set; }
        public long DownloadedBytes { get; set; }
        public double Progress { get; set; }
        public string Status { get; set; } = string.Empty;
        public bool IsPaused { get; set; }
        public DateTime StartTime { get; set; }
        public DateTime? CompletedTime { get; set; }
        
        public SerializableTask() { }
        
        public SerializableTask(DownloadTask task)
        {
            Id = task.Id;
            FileName = task.FileName;
            Url = task.Url;
            FilePath = task.FilePath;
            SavePath = task.SavePath;
            TotalBytes = task.TotalBytes;
            DownloadedBytes = task.DownloadedBytes;
            Progress = task.Progress;
            Status = task.Status;
            IsPaused = task.IsPaused;
            StartTime = task.StartTime;
            CompletedTime = task.CompletedTime;
        }
        
        public DownloadTask ToDownloadTask()
        {
            var task = new DownloadTask
            {
                Id = this.Id,
                FileName = this.FileName,
                Url = this.Url,
                FilePath = this.FilePath,
                SavePath = this.SavePath,
                TotalBytes = this.TotalBytes,
                DownloadedBytes = this.DownloadedBytes,
                Progress = this.Progress,
                Status = this.Status,
                IsPaused = this.IsPaused,
                StartTime = this.StartTime,
                CompletedTime = this.CompletedTime,
                CancellationTokenSource = new CancellationTokenSource()
            };
            
            return task;
        }
    }
}